package com.app.framework.utils;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Redis工具类
 */
public class RedisUtils {

    private static final RedisTemplate<String, Object> redisTemplate = StringsUtils.getBean("redisTemplate", RedisTemplate.class);

    //--------------------------------------------------------------|↓|Redis操作Vo或Po类|↓|-----------------------------------------------------------------
    //--------------------------------------------------------------|↓|Redis操作Vo或Po类|↓|-----------------------------------------------------------------
    //--------------------------------------------------------------|↓|Redis操作Vo或Po类|↓|-----------------------------------------------------------------

    /**
     * 写入Json对象
     *
     * @param key     RedisKey
     * @param hashKey 哈希Key
     * @param TClass  操作类(Vo或Po)
     */
    public static <T> void setJsonHash(String key, Long hashKey, T TClass) {
        redisTemplate.opsForHash().put(key, String.valueOf(hashKey), TClass);
    }

    /**
     * 获取Json对象
     *
     * @param key     RedisKey
     * @param hashKey 哈希Key
     * @param TClass  操作类(Vo或Po)
     */
    public static <T> T getJsonHash(String key, Long hashKey, Class<T> TClass) {
        Object object = redisTemplate.opsForHash().get(key, String.valueOf(hashKey));
        return TClass.cast(object);
    }

    /**
     * 获取所有对象
     *
     * @param key    RedisKey
     * @param TClass 操作类(Vo或Po)
     */
    public static <T> List<T> getAllJsonHash(String key, Class<T> TClass) {
        List<T> result = new ArrayList<>();
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
        for (Object value : entries.values()) {
            result.add(TClass.cast(value));
        }
        return result;
    }

    /**
     * 模糊获取所有对象
     *
     * @param keyPattern RedisKey模式
     * @param TClass     操作类(Vo或Po)
     */
    public static <T> List<T> getAllJsonHashes(String keyPattern, Class<T> TClass) {
        List<T> result = new ArrayList<>();
        Set<String> keys = redisTemplate.keys(keyPattern);
        if (keys != null) {
            for (String key : keys) {
                Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
                for (Object value : entries.values()) {
                    result.add(TClass.cast(value));
                }
            }
        }
        return result;
    }

    /**
     * 判断Json对象是否存在
     *
     * @param key     RedisKey
     * @param hashKey 哈希Key
     */
    public static boolean existsHashField(String key, Long hashKey) {
        return redisTemplate.opsForHash().hasKey(key, String.valueOf(hashKey));
    }

    /**
     * 删除Json对象
     *
     * @param key     RedisKey
     * @param hashKey 哈希Key
     */
    public static void deleteJsonHash(String key, Long hashKey) {
        redisTemplate.opsForHash().delete(key, String.valueOf(hashKey));
    }

    //--------------------------------------------------------------|↓|登录方法|↓|-----------------------------------------------------------------
    //--------------------------------------------------------------|↓|登录方法|↓|-----------------------------------------------------------------
    //--------------------------------------------------------------|↓|登录方法|↓|-----------------------------------------------------------------

    /**
     * 写入Token(24小时过期)
     *
     * @param key   RedisKey
     * @param value 写入的对象
     */
    public static void setToken(String key, Object value) {
        redisTemplate.opsForValue().set("token:" + key, value, 60 * 60 * 24L, TimeUnit.SECONDS);
    }

    //--------------------------------------------------------------|↓|公共方法|↓|-----------------------------------------------------------------
    //--------------------------------------------------------------|↓|公共方法|↓|-----------------------------------------------------------------
    //--------------------------------------------------------------|↓|公共方法|↓|-----------------------------------------------------------------

    /**
     * 将指定键的值 + 1
     *
     * @param key RedisKey
     */
    public static void increment(String key) {
        redisTemplate.opsForValue().increment(key);
    }

    /**
     * Redis setNX
     *
     * @param key   RedisKey
     * @param value 对象
     * @param time  过期时间
     */
    public static Boolean setNx(String key, Object value, long time) {
        return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS));
    }

    /**
     * 写入缓存
     *
     * @param key   RedisKey
     * @param value 对象
     */
    public static void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 写入缓存
     *
     * @param key   RedisKey
     * @param value 对象
     * @param time  过期时间
     */
    public static void set(String key, Object value, long time) {
        set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 写入缓存
     *
     * @param key      RedisKey
     * @param value    对象
     * @param time     过期时间
     * @param timeUnit 过期时间的时间单位
     */
    public static void set(String key, Object value, long time, TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, time, timeUnit);
    }

    /**
     * 获取缓存
     *
     * @param key RedisKey
     */
    public static <T> T get(String key) {
        @SuppressWarnings("unchecked")
        T value = (T) redisTemplate.opsForValue().get(key);
        return value;
    }

    /**
     * 删除缓存
     *
     * @param key RedisKey
     */
    public static void del(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 模糊删除
     *
     * @param keyPattern RedisKey
     */
    public static void concatDeletes(Object keyPattern) {
        Set<String> keys = redisTemplate.keys((String) keyPattern);
        if (CollectionUtils.isNotEmpty(keys)) {
            redisTemplate.delete(keys);
        }
    }

    /**
     * 模糊匹配删除
     */
    public static void deleteKeysContaining(String pattern) {
        Set<String> keys = redisTemplate.keys("*" + pattern + "*");
        if (CollectionUtils.isNotEmpty(keys)) {
            redisTemplate.delete(keys);
        }
    }

    /**
     * 删除集合
     *
     * @param keys Redis键名列表
     */
    public static Long del(List<String> keys) {
        return redisTemplate.delete(keys);
    }

    /**
     * 删除集合对象
     *
     * @param collection 需要删除的键集合
     */
    public static long deleteObject(Collection<?> collection) {
        long count = 0;
        for (Object obj : collection) {
            Boolean deleted = redisTemplate.delete(obj.toString());
            if (deleted != null && deleted) {
                count++;
            }
        }
        return count;
    }

    /**
     * 对应的值进行自增
     *
     * @param key   RedisKey
     * @param delta 自增的数量
     */
    public static void increment(String key, long delta) {
        redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param pattern 类型的参数
     */
    public static Collection<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * 设置过期时间
     *
     * @param key  RedisKey
     * @param time 设置的过期时间
     */
    public static Boolean expire(String key, long time) {
        return expire(key, time, TimeUnit.SECONDS);
    }

    /**
     * 设置过期时间
     *
     * @param key      设置过期时间的Redis key
     * @param time     过期时间的数值
     * @param timeUnit 过期时间的时间单位
     */
    public static Boolean expire(String key, long time, TimeUnit timeUnit) {
        return redisTemplate.expire(key, time, timeUnit);
    }

    /**
     * 获取剩余过期时间
     *
     * @param key Redis key
     */
    public static Long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key RedisKey
     */
    public static Boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 批量获取数据
     *
     * @param keys keys
     */
    public static List<Object> getMulti(List<String> keys) {
        return redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 新增一个
     *
     * @param key   RedisKey
     * @param value 值
     */
    public static void add(String key, Map<String, String> value) {
        redisTemplate.opsForSet().add(key, value);
    }

    /**
     * 删除集合中的值
     *
     * @param key   RedisKey
     * @param value 值
     */
    public static void remove(String key, String value) {
        redisTemplate.opsForSet().remove(key, value);
    }

    /**
     * 判断是否包含
     *
     * @param key   RedisKey
     * @param value 值
     */
    public static void contains(String key, String value) {
        redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 获取集合中所有的值
     *
     * @param key RedisKey
     */
    public static Set<Object> values(String key) {
        return redisTemplate.opsForSet().members(key);
    }

}